{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "lPboLx_o0UxI"
   },
   "source": [
    "# 实验8 基于全连接深度神经网络模型的手写识别及Wi-Fi动作感知\n",
    "1.读取MNIST和Wi-Fi动作感知数据，并转化为相同的形式）\n",
    "\n",
    "2.使用训练数据生成DataSet和DataLoader对象用于模型训练\n",
    "\n",
    "3.使用torch.nn定义FNN类，自定隐藏层数和节点数量\n",
    "\n",
    "4.用Adam的优化方式训练模型\n",
    "\n",
    "5.在验证或测试集上测试模型性能，画出学习曲线并分析结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.读取MNIST和Wi-Fi动作感知数据，并转化为相同的形式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 1000
    },
    "id": "sM-ziKb94S9_",
    "outputId": "9a8bd59b-1ed4-47e3-e118-cee1849a610a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n",
      "Number of training samples: 43360\n",
      "Number of cross-validation samples: 10850\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "class FlattenTransform:\n",
    "    def __call__(self, tensor):\n",
    "        ''' \n",
    "        Flatten tensor into an 1-D vector\n",
    "        '''\n",
    "        return tensor.view(-1)\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    FlattenTransform()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.8\n",
    "\n",
    "# Create a list to store indices for each class\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])\n",
    "\n",
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.使用训练数据生成DataSet和DataLoader对象用于模型训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "BWPSDyOq5qOO",
    "outputId": "9aed06f2-67a9-4a6f-f00c-d91554c3a260"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input_size is 784\n",
      "tensor([[0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "input_size = data[0].numpy().shape[0]\n",
    "print(f'Input_size is {input_size}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.使用torch.nn定义FNN类，自定隐藏层数和节点数量\n",
    "* 输入：1-D向量\n",
    "* 输出：手写字母类型的概率分布\n",
    "* 隐藏层：2层\n",
    "* 节点数：100个/层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FNN(\n",
      "  (fc1): Linear(in_features=784, out_features=10, bias=True)\n",
      "  (relu1): ReLU()\n",
      "  (fc2): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (relu2): ReLU()\n",
      "  (fc3): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_classes):\n",
    "        super(FNN, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, hidden_size)\n",
    "        self.relu2 = nn.ReLU()\n",
    "        self.fc3 = nn.Linear(hidden_size, num_classes)\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu1(x)\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu2(x)\n",
    "        x = self.fc3(x)\n",
    "        out = self.softmax(x)\n",
    "        return out\n",
    "\n",
    "# Define the model parameters\n",
    "hidden_size = 10\n",
    "num_classes = 10  # MNIST has 10 classes (digits 0-9)\n",
    "\n",
    "# Instantiate the model\n",
    "model = FNN(input_size, hidden_size, num_classes)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.使用Adam作为Optimizor训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/50], Train Loss: 1.8006, CV Loss: 1.6737\n",
      "Epoch [2/50], Train Loss: 1.6576, CV Loss: 1.6533\n",
      "Epoch [3/50], Train Loss: 1.6438, CV Loss: 1.6455\n",
      "Epoch [4/50], Train Loss: 1.6370, CV Loss: 1.6406\n",
      "Epoch [5/50], Train Loss: 1.6323, CV Loss: 1.6390\n",
      "Epoch [6/50], Train Loss: 1.6288, CV Loss: 1.6363\n",
      "Epoch [7/50], Train Loss: 1.5757, CV Loss: 1.5723\n",
      "Epoch [8/50], Train Loss: 1.5589, CV Loss: 1.5628\n",
      "Epoch [9/50], Train Loss: 1.5541, CV Loss: 1.5609\n",
      "Epoch [10/50], Train Loss: 1.5498, CV Loss: 1.5599\n",
      "Epoch [11/50], Train Loss: 1.5477, CV Loss: 1.5589\n",
      "Epoch [12/50], Train Loss: 1.5455, CV Loss: 1.5592\n",
      "Epoch [13/50], Train Loss: 1.5438, CV Loss: 1.5576\n",
      "Epoch [14/50], Train Loss: 1.5419, CV Loss: 1.5549\n",
      "Epoch [15/50], Train Loss: 1.5408, CV Loss: 1.5530\n",
      "Epoch [16/50], Train Loss: 1.5393, CV Loss: 1.5534\n",
      "Epoch [17/50], Train Loss: 1.5382, CV Loss: 1.5519\n",
      "Epoch [18/50], Train Loss: 1.5371, CV Loss: 1.5556\n",
      "Epoch [19/50], Train Loss: 1.5361, CV Loss: 1.5506\n",
      "Epoch [20/50], Train Loss: 1.5358, CV Loss: 1.5506\n",
      "Epoch [21/50], Train Loss: 1.5338, CV Loss: 1.5512\n",
      "Epoch [22/50], Train Loss: 1.5330, CV Loss: 1.5498\n",
      "Epoch [23/50], Train Loss: 1.5319, CV Loss: 1.5483\n",
      "Epoch [24/50], Train Loss: 1.5316, CV Loss: 1.5482\n",
      "Epoch [25/50], Train Loss: 1.5308, CV Loss: 1.5496\n",
      "Epoch [26/50], Train Loss: 1.5294, CV Loss: 1.5465\n",
      "Epoch [27/50], Train Loss: 1.5284, CV Loss: 1.5458\n",
      "Epoch [28/50], Train Loss: 1.5280, CV Loss: 1.5489\n",
      "Epoch [29/50], Train Loss: 1.5276, CV Loss: 1.5468\n",
      "Epoch [30/50], Train Loss: 1.5264, CV Loss: 1.5476\n",
      "Epoch [31/50], Train Loss: 1.5254, CV Loss: 1.5482\n",
      "Epoch [32/50], Train Loss: 1.5254, CV Loss: 1.5471\n",
      "Epoch [33/50], Train Loss: 1.5244, CV Loss: 1.5463\n",
      "Epoch [34/50], Train Loss: 1.5236, CV Loss: 1.5488\n",
      "Epoch [35/50], Train Loss: 1.5231, CV Loss: 1.5450\n",
      "Epoch [36/50], Train Loss: 1.5226, CV Loss: 1.5459\n",
      "Epoch [37/50], Train Loss: 1.5224, CV Loss: 1.5463\n",
      "Epoch [38/50], Train Loss: 1.5219, CV Loss: 1.5455\n",
      "Epoch [39/50], Train Loss: 1.5213, CV Loss: 1.5446\n",
      "Epoch [40/50], Train Loss: 1.5206, CV Loss: 1.5453\n",
      "Epoch [41/50], Train Loss: 1.5204, CV Loss: 1.5447\n",
      "Epoch [42/50], Train Loss: 1.5198, CV Loss: 1.5455\n",
      "Epoch [43/50], Train Loss: 1.5198, CV Loss: 1.5441\n",
      "Epoch [44/50], Train Loss: 1.5188, CV Loss: 1.5457\n",
      "Epoch [45/50], Train Loss: 1.5188, CV Loss: 1.5453\n",
      "Epoch [46/50], Train Loss: 1.5182, CV Loss: 1.5481\n",
      "Epoch [47/50], Train Loss: 1.5178, CV Loss: 1.5459\n",
      "Epoch [48/50], Train Loss: 1.5177, CV Loss: 1.5457\n",
      "Epoch [49/50], Train Loss: 1.5171, CV Loss: 1.5441\n",
      "Epoch [50/50], Train Loss: 1.5165, CV Loss: 1.5479\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters())\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 50\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.在验证或测试集上测试模型性能，画出学习曲线并分析结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 94.37%\n",
      "Accuracy on cross-validation set: 91.24%\n"
     ]
    },
    {
     "data": {
      "image/png": "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DHHuxaXhKi8vD+3atcPSpUsrtP+vv/6KCRMmYMqUKTh58iS+/fZbHD58GFOnTrXvc+DAAYwZMwbjx4/HsWPHMH78eIwePRq///57dX0MIiIiIqohKSkp9mXx4sXw8fFxWLdkyRKH/U0mU4XOGxAQAG9v7wrXIZfLERoaCoWCg29TEZeGq8GDB2P+/PkYMWJEhfY/ePAgGjVqhGeeeQYxMTG488478a9//QtHjhyx77N48WLcfffdmDVrFuLi4jBr1iz0798fixcvrqZPUb0+2XcB97y3Fyt+TXR1KURERFTHiaKIfKPZJYsoihWqMTQ01L74+vpCEAT7a71eDz8/P3zzzTfo27cvNBoNvvzyS2RkZODhhx9GREQEtFot2rRpg9WrVzuc9+ZugY0aNcIbb7yBRx99FN7e3oiKisLHH39s335zi9KePXsgCAJ27tyJTp06QavVokePHjh79qzD+8yfPx/BwcHw9vbG1KlT8Z///Ad33HFHpb5fAGAwGPDMM88gODgYGo0Gd955Jw4fPmzffuPGDYwbNw5BQUHw8PBAbGwsVq1aBUAaiv+pp55CWFgYNBoNGjVqhAULFlS6FnKzea569OiBl19+GZs2bcLgwYORlpaG7777Dvfee699nwMHDuD//u//HI4bOHBgueHKYDDAYDDYX+t0OqfXXllZBUb8fS0XyZmcNZ2IiIiqV4HJgpavbXXJe5/670BoVc751fTFF1/EO++8g1WrVkGtVkOv16Njx4548cUX4ePjg59//hnjx49H48aN0bVr1zLP884772DevHl46aWX8N133+HJJ59E7969ERcXV+YxL7/8Mt555x0EBQXhiSeewKOPPorffvsNgHR7y+uvv46PPvoIPXv2xJo1a/DOO+8gJiam0p/13//+N9atW4fPPvsM0dHRWLRoEQYOHIjz588jICAAr776Kk6dOoXNmzejQYMGOH/+PAoKCgAA77//PjZu3IhvvvkGUVFRSE5ORnJycqVrITcMV1999RXGjBkDvV4Ps9mM+++/Hx988IF9n9TUVISEhDgcFxISgtTU1DLPu2DBAsydO7fa6q6KAE81ACAjz+jiSoiIiIjcw4wZM0r0jHr++eftz59++mls2bIF3377bbnhasiQIZg2bRoAKbC999572LNnT7nh6vXXX0efPn0AAP/5z39w7733Qq/XQ6PR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s2dPnDt3rsxzLViwwN4q5uvri8jIyOouv0rs4Sqf4YqIiIiIqLZw23AVHx8PPz8/DB8+3GF9t27d8Mgjj6Bdu3bo1asXvvnmGzRr1gwffPBBmeeaNWsWsrOz7UtycnI1V181HC2QiIiIiKj2cek9V5UliiJWrlyJ8ePHQ6VSlbuvTCZD586dy225UqvVUKvVzi6z2vjb5rniPVdERERERLWGW7Zc7d27F+fPn8eUKVNuua8oikhISEBYWFgNVFYz2HJFRERERFT7uLTlKjc3F+fPn7e/TkxMREJCAgICAhAVFYVZs2bhypUr+Pzzzx2OW7FiBbp27YrWrVuXOOfcuXPRrVs3xMbGQqfT4f3330dCQgI+/PDDav88NcV2z1WByYICowUeKrmLKyIiIiIiIpeGqyNHjqBfv3721zNnzgQATJw4EfHx8UhJSUFSUpLDMdnZ2Vi3bh2WLFlS6jmzsrLw+OOPIzU1Fb6+vmjfvj327duHLl26VN8HqWFeagVUchmMFisy8gyIUGldXRIRERERUb0niKIourqI2kan08HX1xfZ2dnw8fFxdTml6vbGTqTq9Nj4VE+0jfBzdTlERERERHXS7WQDt7znioq6BmbwvisiIiIiolqB4cpNBXoVDmrBEQOJiIiIiGoFhis3FcARA4mIiIiIahWGKzdlD1f5DFdERERERLUBw5WbCtCyWyARERERUW3CcOWmArw4oAURERERUW3CcOWmAu33XBlcXAkREREREQEMV24rwFMNgANaEBERERHVFgxXborzXBERERER1S4MV27K1i0wR2+G0Wx1cTVERERERMRw5aZ8PZSQywQAwA0Ox05ERERE5HIMV25KJhPgr1UCADI4HDsRERERkcsxXLkx231XbLkiIiIiInI9his35q/loBZERERERLUFw5UbCyycSDgzl3NdERERERG5GsOVGwuwTyTMlisiIiIiIldjuHJjtomE2S2QiIiIiMj1GK7cWCBbroiIiIiIag2GKzdm6xbIlisiIiIiItdjuHJjbLkiIiIiIqo9GK7cWIAXwxURERERUW3BcOXGbN0Cs/KNsFhFF1dDRERERFS/MVy5MdskwlYRyC4wubgaIiIiIqL6jeHKjSnlMvhoFACAzDxOJExERERE5EoMV24u0Ktwrqtc3ndFRERERORKDFduLoAjBhIRERER1QoMV26Oc10REREREdUODFdujnNdERERERHVDgxXbo7dAomIiIiIageGKzfHboFERERERLUDw5WbC/SytVxxKHYiIiIiIldiuHJztomEM/M4iTARERERkSsxXLm5QE9pniu2XBERERERuRbDlZsL8Coa0EIURRdXQ0RERERUfzFcuTnbUOwmi4gcg9nF1RARERER1V8MV25Oo5RDq5IDADJzOWIgEREREZGrMFzVARyOnYiIiIjI9Riu6oBATiRMRERERORyDFd1QIAn57oiIiIiInI1hqs6IKBwOHZ2CyQiIiIich2GqzogwFMJALjBcEVERERE5DIMV3UAW66IiIiIiFyP4aoO4IAWRERERESux3BVBwQwXBERERERuRzDVR0Q4FU4zxUnESYiIiIichmGqzqA3QKJiIiIiFyP4aoOsHULLDBZUGC0uLgaIiIiIqL6ieGqDvBSK6CSS9/KDE4kTERERETkEgxXdYAgCPAvnOuKXQOJiIiIiFyD4aqOsM11xXBFREREROQaLg1X+/btw9ChQxEeHg5BELBhw4Zy9580aRIEQSixtGrVymG/devWoWXLllCr1WjZsiXWr19fjZ+iduCgFkREREREruXScJWXl4d27dph6dKlFdp/yZIlSElJsS/JyckICAjAgw8+aN/nwIEDGDNmDMaPH49jx45h/PjxGD16NH7//ffq+hi1Aue6IiIiIiJyLYUr33zw4MEYPHhwhff39fWFr6+v/fWGDRtw48YNTJ482b5u8eLFuPvuuzFr1iwAwKxZs7B3714sXrwYq1evdl7xtYwtXGUwXBERERERuYRb33O1YsUKDBgwANHR0fZ1Bw4cwD333OOw38CBA7F///4yz2MwGKDT6RwWd2PvFsiJhImIiIiIXMJtw1VKSgo2b96MqVOnOqxPTU1FSEiIw7qQkBCkpqaWea4FCxbYW8V8fX0RGRlZLTVXpwAvtlwREREREbmS24ar+Ph4+Pn5Yfjw4SW2CYLg8FoUxRLrips1axays7PtS3JysrPLrXZFA1pwnisiIiIiIldw6T1XlSWKIlauXInx48dDpVI5bAsNDS3RSpWWllaiNas4tVoNtVpdLbXWFA7FTkRERETkWm7ZcrV3716cP38eU6ZMKbGte/fu2L59u8O6bdu2oUePHjVVnksEFE4izG6BRERERESu4dKWq9zcXJw/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uVc7GxERERERUS3FcEVEREREROQEDFdEREREREROwHBFRERERETkBAxXRERERERETsBwRURERERE5AQMV0RERERERE7AcEVEREREROQEDFdEREREREROwHBFRERERETkBAxXRERERERETsBwRURERERE5AQMV0RERERERE7AcEVEREREROQEClcXUBuJoggA0Ol0Lq6EiIiIiIhcyZYJbBmhPAxXpcjJyQEAREZGurgSIiIiIiKqDXJycuDr61vuPoJYkQhWz1itVly9ehXe3t4QBMEp59TpdIiMjERycjJ8fHycck6qP3j9UFXw+qHK4rVDVcHrh6qiNl0/oigiJycH4eHhkMnKv6uKLVelkMlkiIiIqJZz+/j4uPwCIffF64eqgtcPVRavHaoKXj9UFbXl+rlVi5UNB7QgIiIiIiJyAoYrIiIiIiIiJ2C4qiFqtRqzZ8+GWq12dSnkhnj9UFXw+qHK4rVDVcHrh6rCXa8fDmhBRERERETkBGy5IiIiIiIicgKGKyIiIiIiIidguCIiIiIiInIChisiIiIiIiInYLiqIR999BFiYmKg0WjQsWNH/PLLL64uiWqhffv2YejQoQgPD4cgCNiwYYPDdlEUMWfOHISHh8PDwwN9+/bFyZMnXVMs1SoLFixA586d4e3tjeDgYAwfPhxnz5512IfXD5Vl2bJlaNu2rX2yzu7du2Pz5s327bx2qKIWLFgAQRAwY8YM+zpeP1SWOXPmQBAEhyU0NNS+3R2vHYarGrB27VrMmDEDL7/8Mo4ePYpevXph8ODBSEpKcnVpVMvk5eWhXbt2WLp0aanbFy1ahHfffRdLly7F4cOHERoairvvvhs5OTk1XCnVNnv37sX06dNx8OBBbN++HWazGffccw/y8vLs+/D6obJERETgzTffxJEjR3DkyBHcddddGDZsmP2XGF47VBGHDx/Gxx9/jLZt2zqs5/VD5WnVqhVSUlLsy4kTJ+zb3PLaEanadenSRXziiScc1sXFxYn/+c9/XFQRuQMA4vr16+2vrVarGBoaKr755pv2dXq9XvT19RWXL1/uggqpNktLSxMBiHv37hVFkdcP3T5/f3/x008/5bVDFZKTkyPGxsaK27dvF/v06SM+++yzoijy3x4q3+zZs8V27dqVus1drx22XFUzo9GIP/74A/fcc4/D+nvuuQf79+93UVXkjhITE5GamupwLanVavTp04fXEpWQnZ0NAAgICADA64cqzmKxYM2aNcjLy0P37t157VCFTJ8+Hffeey8GDBjgsJ7XD93KuXPnEB4ejpiYGDz00EO4cOECAPe9dhSuLqCuS09Ph8ViQUhIiMP6kJAQpKamuqgqcke266W0a+nSpUuuKIlqKVEUMXPmTNx5551o3bo1AF4/dGsnTpxA9+7dodfr4eXlhfXr16Nly5b2X2J47VBZ1qxZgz/++ANHjhwpsY3/9lB5unbtis8//xzNmjXDtWvXMH/+fPTo0QMnT55022uH4aqGCILg8FoUxRLriCqC1xLdylNPPYXjx4/j119/LbGN1w+VpXnz5khISEBWVhbWrVuHiRMnYu/evfbtvHaoNMnJyXj22Wexbds2aDSaMvfj9UOlGTx4sP15mzZt0L17dzRp0gSfffYZunXrBsD9rh12C6xmDRo0gFwuL9FKlZaWViKJE5XHNnoOryUqz9NPP42NGzdi9+7diIiIsK/n9UO3olKp0LRpU3Tq1AkLFixAu3btsGTJEl47VK4//vgDaWlp6NixIxQKBRQKBfbu3Yv3338fCoXCfo3w+qGK8PT0RJs2bXDu3Dm3/beH4aqaqVQqdOzYEdu3b3dYv337dvTo0cNFVZE7iomJQWhoqMO1ZDQasXfvXl5LBFEU8dRTT+H777/Hrl27EBMT47Cd1w/dLlEUYTAYeO1Qufr3748TJ04gISHBvnTq1Anjxo1DQkICGjduzOuHKsxgMOD06dMICwtz23972C2wBsycORPjx49Hp06d0L17d3z88cdISkrCE0884erSqJbJzc3F+fPn7a8TExORkJCAgIAAREVFYcaMGXjjjTcQGxuL2NhYvPHGG9BqtRg7dqwLq6baYPr06fj666/xww8/wNvb2/6XPl9fX3h4eNjnneH1Q6V56aWXMHjwYERGRiInJwdr1qzBnj17sGXLFl47VC5vb2/7vZ02np6eCAwMtK/n9UNlef755zF06FBERUUhLS0N8+fPh06nw8SJE9333x6XjVNYz3z44YdidHS0qFKpxA4dOtiHRyYqbvfu3SKAEsvEiRNFUZSGJZ09e7YYGhoqqtVqsXfv3uKJEydcWzTVCqVdNwDEVatW2ffh9UNlefTRR+3/RwUFBYn9+/cXt23bZt/Oa4duR/Gh2EWR1w+VbcyYMWJYWJioVCrF8PBwccSIEeLJkyft293x2hFEURRdlOuIiIiIiIjqDN5zRURERERE5AQMV0RERERERE7AcEVEREREROQEDFdEREREREROwHBFRERERETkBAxXRERERERETsBwRURERERE5AQMV0RERERERE7AcEVERORkgiBgw4YNri6DiIhqGMMVERHVKZMmTYIgCCWWQYMGubo0IiKq4xSuLoCIiMjZBg0ahFWrVjmsU6vVLqqGiIjqC7ZcERFRnaNWqxEaGuqw+Pv7A5C67C1btgyDBw+Gh4cHYmJi8O233zocf+LECdx1113w8PBAYGAgHn/8ceTm5jrss3LlSrRq1QpqtRphYWF46qmnHLanp6fjgQcegFarRWxsLDZu3Fi9H5qIiFyO4YqIiOqdV199FSNHjsSxY8fwyCOP4OGHH8bp06cBAPn5+Rg0aBD8/f1x+PBhfPvtt9ixY4dDeFq2bBmmT5+Oxx9/HCdOnMDGjRvRtGlTh/eYO3cuRo8ejePHj2PIkCEYN24cMjMza/RzEhFRzRJEURRdXQQREZGzTJo0CV9++SU0Go3D+hdffBGvvvoqBEHAE088gWXLltm3devWDR06dMBHH32ETz75BC+++CKSk5Ph6ekJANi0aROGDh2Kq1evIiQkBA0bNsTkyZMxf/78UmsQBAGvvPIK5s2bBwDIy8uDt7c3Nm3axHu/iIjqMN5zRUREdU6/fv0cwhMABAQE2J93797dYVv37t2RkJAAADh9+jTatWtnD1YA0LNnT1itVpw9exaCIODq1avo379/uTW0bdvW/tzT0xPe3t5IS0ur7EciIiI3wHBFRER1jqenZ4luerciCAIAQBRF+/PS9vHw8KjQ+ZRKZYljrVbrbdVERETuhfdcERFRvXPw4MESr+Pi4gAALVu2REJCAvLy8uzbf/vtN8hkMjRr1gze3t5o1KgRdu7cWaM1ExFR7ceWKyIiqnMMBgNSU1Md1ikUCjRo0AAA8O2336JTp06488478dVXX+HQoUNYsWIFAGDcuHGYPXs2Jk6ciDlz5uD69et4+umnMX78eISEhAAA5syZgyeeeALBwcEYPHgwcnJy8Ntvv+Hpp5+u2Q9KRES1CsMVERHVOVu2bEFYWJjDuubNm+PMmTMApJH81qxZg2nTpiE0NBRfffUVWrZsCQDQarXYunUrnn32WXTu3BlarRYjR47Eu+++az/XxIkTodfr8d577+H5559HgwYNMGrUqJr7gEREVCtxtEAiIqpXBEHA+vXrMXz4cFeXQkREdQzvuSIiIiIiInIChisiIiIiIiIn4D1XRERUr7A3PBERVRe2XBERERERETkBwxUREREREZETMFwRERERERE5AcMVERERERGREzBcEREREREROQHDFRERERERkRMwXBERERERETkBwxUREREREZET/D9ftkeGwNGFiQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # Cross-validation set accuracy\n",
    "    cv_correct = 0\n",
    "    cv_total = 0\n",
    "    for images, labels in cvLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        cv_total += labels.size(0)\n",
    "        cv_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training and Cross-Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "authorship_tag": "ABX9TyO5gS9/MePw+FDiXJA07L6y",
   "include_colab_link": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
